package cn.wolfcode.shop.cloud.web.controller;

import cn.wolfcode.shop.cloud.common.BusinessException;
import cn.wolfcode.shop.cloud.common.Result;
import cn.wolfcode.shop.cloud.domain.User;
import cn.wolfcode.shop.cloud.mq.MQConstans;
import cn.wolfcode.shop.cloud.mq.OrderMessage;
import cn.wolfcode.shop.cloud.msg.SeckillCodeMsg;
import cn.wolfcode.shop.cloud.service.ISeckillGoodService;
import cn.wolfcode.shop.cloud.service.ISeckillOrderInfoService;
import cn.wolfcode.shop.cloud.service.ISeckillOrderService;
import cn.wolfcode.shop.cloud.service.RedisService;
import cn.wolfcode.shop.cloud.util.SeckillKeyPrefix;
import cn.wolfcode.shop.cloud.util.UserValidAnno;
import cn.wolfcode.shop.cloud.vo.SeckillGoodVo;
import domain.OrderInfo;
import domain.SeckillOrder;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

@RestController
public class SeckillOrderInfoController {
    @Autowired
    private ISeckillGoodService seckillGoodService;
    @Autowired
    private ISeckillOrderService seckillOrderService;
    @Autowired
    private ISeckillOrderInfoService seckillOrderInfoService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    public static final ConcurrentHashMap<Long, Boolean> local_flag = new ConcurrentHashMap<>();


    //int count = 10;

    @RequestMapping("/{path}/doSeckill")
    public Result doSeckill(@PathVariable String path, Long seckillId, @UserValidAnno User user, String uuid) {
        //1.判断是否登录,用户未登录.提示用户违法操作
        if (user == null) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_NOT_LOGIN_ERROR);
        }

        //判断路径是否合法
        String redisPath = redisService.get(SeckillKeyPrefix.SECKILL_PATH, uuid, String.class);
        if (StringUtils.isEmpty(redisPath) || !path.equals(redisPath)) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_STOCKET_OVER);
        }


        //判断一下本地标识
        Boolean flag = SeckillOrderInfoController.local_flag.get(seckillId);
        //此时说明redis数据减为负数
        if (flag != null && flag) {
            System.out.println("此处是redis中大量网络开销");
            throw new BusinessException(SeckillCodeMsg.SECKLILL_STOCKET_OVER);
        }


        //2.判断秒杀商品的id,上数据库查询有无数据,没有数据提示违法操作
        SeckillGoodVo seckillGoodVo = seckillGoodService.queryByIdCache(seckillId);
        if (seckillGoodVo == null) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_OPT);
        }
        //3.判断商品的秒杀时间是否开始,如果未开始或已经结束,提示用户违法操作
        Date now = new Date();
        if (now.getTime() - seckillGoodVo.getStartDate().getTime() < 0 ||
                now.getTime() - seckillGoodVo.getEndDate().getTime() > 0) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_OPT);
        }
        //4.判断用户是否重复下单,如果重复下单,提示不要重复下单
        //SeckillOrder seckillOrder = seckillOrderService.queryByUserIdAndSeckillId(user.getId(), seckillId);
        //if(seckillOrder !=null){}

        //判断redis中是否存在key值,存在则为重复
        if (redisService.exists(SeckillKeyPrefix.SECKILL_ORDER, user.getId() + ":" + seckillId)) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_REOEAT_ERROR);
        }

        //count-- 不是原子性操作,多线程操作取值就会出现问题
        //3步  1 从内存中取值,2.减减操作3.赋值操作
        //count--;
        //if (count < 0) {
        //throw new BusinessException();
        //}

        //5.判断是否有库存,如果没有库存,提示请不要重复下单
        //十个请求订单所以就不用了
//        if (seckillGoodVo.getStockCount() <= 0) {
//            throw new BusinessException(SeckillCodeMsg.SECKLILL_STOCKET_OVER);
//        }
        //对于redis中数据进行操作
        long count = redisService.decr(SeckillKeyPrefix.SECKILL_STOCK_COUNT, seckillId + "");
        if (count < 0) {

            SeckillOrderInfoController.local_flag.put(seckillId, true);
            throw new BusinessException(SeckillCodeMsg.SECKLILL_STOCKET_OVER);

        }
        //6.秒杀
        //6.1 减库存
        //6.2 创建出来订单信息保存到数据库中
        //6.3 往t_seckill_order 去存储一条数据
        //doSeckill往表里插入数据
        //String orderNo = seckillOrderInfoService.doSeckill(user.getId(), seckillId);
        //发送异步请求
        //需要seckillId userId,传过去一个  OrderMessgae
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setSeckillId(seckillId);
        orderMessage.setUserId(user.getId());
        orderMessage.setUuid(uuid);
        rocketMQTemplate.syncSend(MQConstans.CREATE_ORDER_DEST, orderMessage);
        return Result.success("正在抢购中.....");
    }

    @RequestMapping("/queryByOrderNo")
    public Result queryByOrderNo(String orderNo, @UserValidAnno User user) {
        //1.判断是否登录,用户未登录.提示用户违法操作
        if (user == null) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_NOT_LOGIN_ERROR);
        }
        //根据订单编号查询订单
        OrderInfo orderInfo = seckillOrderInfoService.queryByOrderNo(orderNo);
        if (orderInfo == null) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_OPT);
        }
        //用户只能看自己订单的信息
        if (!user.getId().equals(orderInfo.getUserId())) {
            throw new BusinessException(SeckillCodeMsg.SECKLILL_OPT);

        }
        return Result.success(orderInfo);
    }
}
